package org.polyforms.repository.datanucleus;

import java.lang.reflect.Field;

import javax.persistence.Query;

import org.apache.commons.lang.StringUtils;
import org.polyforms.repository.spi.QueryParameterResolver;
import org.springframework.util.ReflectionUtils;

/**
 * Implementation of {@link QueryParameterResolver} for Datanucleus.
 * 
 * @author Kuisong Tong
 * @since 1.0
 */
public final class DatanucleusQueryParameterResolver implements QueryParameterResolver {
    /**
     * {@inheritDoc}
     */
    public Parameter[] getNamedParameters(final Query query) {
        return getNamedParameter(getWhereClause(query));
    }

    private String getWhereClause(final Query query) {
        final Field field = ReflectionUtils.findField(query.getClass(), "query");
        ReflectionUtils.makeAccessible(field);
        final org.datanucleus.store.query.Query nativeQuery = (org.datanucleus.store.query.Query) ReflectionUtils
                .getField(field, query);
        return nativeQuery.getFilter();
    }

    private NamedParameter[] getNamedParameter(final String whereClause) {
        final String[] parameterNames = StringUtils.substringsBetween(whereClause + " ", ":", " ");
        if (parameterNames == null) {
            return new NamedParameter[0];
        }
        final NamedParameter[] parameters = new NamedParameter[parameterNames.length];
        for (int i = 0; i < parameterNames.length; i++) {
            parameters[i] = new NamedParameter(parameterNames[i]);
        }
        return parameters;
    }

    private static final class NamedParameter implements Parameter {
        private final String name;

        /**
         * Create an named parameter.
         */
        public NamedParameter(final String name) {
            this.name = name;
        }

        /**
         * {@inheritDoc}
         */
        public String name() {
            return name;
        }
    }
}
